/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.facebook.presto.obs;

import com.facebook.airlift.log.Logger;
import io.airlift.units.DataSize;
import io.airlift.units.Duration;
import org.apache.hadoop.conf.Configuration;

import javax.inject.Inject;
import java.io.File;

import static io.airlift.units.DataSize.Unit.MEGABYTE;

public class PrestoObsConfigurationUpdater
        implements ObsConfigurationUpdater
{
    private static final Logger log = Logger.get(PrestoObsConfigurationUpdater.class);

    private final String obsAccessKey;
    private final String obsSecretKey;
    private final String endpoint;
    private final String obsSecurityToken;
    private final PrestoObsStorageClass obsStorageClass;
    private final boolean pathStyleAccess;

    private final boolean sslEnabled;

    private final boolean sseEnabled;

    private final PrestoObsSseType sseType;

    private final String sseKmsKeyId;

    private final String sseCKeyBase64;

    private final int maxClientRetries;

    private final int maxErrorRetries;
    private final Duration maxBackoffTime;

    private final Duration maxRetryTime;

    private final Duration connectTimeout;

    private final Duration socketTimeout;

    private final int maxConnections;

    private final File stagingDirectory;

    private final boolean streamingUploadEnabled;

    private final DataSize streamingPartSize;

    private final PrestoObsAclType aclType;

    private final boolean skipGlacierObjects;



    @Inject
    public PrestoObsConfigurationUpdater(HiveObsConfig config)
    {
        this.obsAccessKey = config.getObsAccessKey();
        this.obsSecretKey = config.getObsSecretKey();
        this.endpoint = config.getObsEndpoint();
        this.obsSecurityToken = config.getObsSecurityToken();

        this.obsStorageClass = config.getObsStorageClass();
        this.pathStyleAccess = config.isObsPathStyleAccess();
        this.sslEnabled = config.isObsSslEnabled();
        this.sseEnabled = config.isObsSseEnabled();
        this.sseType = config.getObsSseType();
        this.sseKmsKeyId = config.getObsSseKmsKeyId();
        this.sseCKeyBase64 = config.getObsSseCKeyBase64();

        this.maxClientRetries = config.getObsMaxClientRetries();
        this.maxErrorRetries = config.getObsMaxErrorRetries();

        this.maxBackoffTime =config.getObsMaxBackoffTime();
        this.maxRetryTime = config.getObsMaxRetryTime();

        this.connectTimeout = config.getObsConnectTimeout();
        this.socketTimeout = config.getObsSocketTimeout();

        this.maxConnections = config.getObsMaxConnections();

        this.stagingDirectory = config.getObsStagingDirectory();

        this.streamingUploadEnabled = config.isObsStreamingUploadEnabled();
        this.streamingPartSize = config.getObsStreamingPartSize();

        this.aclType = config.getObsAclType();
        this.skipGlacierObjects = config.isSkipGlacierObjects();
    }

    @Override
    public void updateConfiguration(Configuration config){
        config.set("fs.obs.impl",PrestoObsFileSystem.class.getName());

        if (obsAccessKey != null) {
            config.set(OBS_ACCESS_KEY, obsAccessKey);
        }
        if (obsSecretKey != null) {
            config.set(OBS_SECRET_KEY, obsSecretKey);
        }
        if (endpoint != null) {
            config.set(OBS_ENDPOINT, endpoint);
        }
        if (obsSecurityToken != null) {
            config.set(OBS_SECURITY_TOKEN, obsSecurityToken);
        }

        config.set(OBS_STORAGE_CLASS, obsStorageClass.name());
        config.setBoolean(OBS_PATH_STYLE_ACCESS,pathStyleAccess);
        config.setBoolean(OBS_SSL_ENABLED, sslEnabled);
        config.setBoolean(OBS_SSE_ENABLED, sseEnabled);
        config.set(OBS_SSE_TYPE, sseType.name());
        if(sseKmsKeyId != null){
            config.set(OBS_SSE_KMS_KEY_ID, sseKmsKeyId);
        }
        if(sseCKeyBase64 != null){
            config.set(OBS_SSE_C_KEY_BASE64, sseCKeyBase64);
        }

        config.setInt(OBS_MAX_CLIENT_RETRIES, maxClientRetries);
        config.setInt(OBS_MAX_ERROR_RETRIES, maxErrorRetries);
        config.set(OBS_MAX_BACKOFF_TIME, maxBackoffTime.toString());
        config.set(OBS_MAX_RETRY_TIME, maxRetryTime.toString());
        config.set(OBS_CONNECT_TIMEOUT, connectTimeout.toString());
        config.set(OBS_SOCKET_TIMEOUT, socketTimeout.toString());
        config.setInt(OBS_MAX_CONNECTIONS, maxConnections);

        config.set(OBS_STAGING_DIRECTORY, stagingDirectory.toString());
        config.setBoolean(OBS_STREAMING_UPLOAD_ENABLED, streamingUploadEnabled);
        config.setLong(OBS_STREAMING_UPLOAD_PART_SIZE, streamingPartSize.toBytes());

        config.set(OBS_ACL_TYPE, aclType.name());
        config.setBoolean(OBS_SKIP_GLACIER_OBJECTS, skipGlacierObjects);
    }
}
